import b2 from './../box2d/box2d'

export default class DrawWorld {
	world = null;

	constructor(world) {
		this.world = world;
	}

	drawWorld(context) {
		for (var j = this.world.m_jointList; j; j = j.m_next) {
			this.drawJoint(j, context);
		}
		for (var b = this.world.m_bodyList; b; b = b.m_next) {
			for (var s = b.GetShapeList(); s != null; s = s.GetNext()) {
				this.drawShape(s, context);
			}
		}
	}

	drawJoint(joint, context) {
		var b1 = joint.m_body1;
		var b2 = joint.m_body2;
		var x1 = b1.m_position;
		var x2 = b2.m_position;
		var p1 = joint.GetAnchor1();
		var p2 = joint.GetAnchor2();
		context.strokeStyle = '#00eeee';
		context.beginPath();
		switch (joint.m_type) {
			case b2.Joint.e_distanceJoint:
				context.moveTo(p1.x, p1.y);
				context.lineTo(p2.x, p2.y);
			break;

			case b2.Joint.e_pulleyJoint:
				// TODO
			break;

			default:
				if (b1 == this.world.m_groundBody) {
					context.moveTo(p1.x, p1.y);
					context.lineTo(x2.x, x2.y);
				}
				else if (b2 == this.world.m_groundBody) {
					context.moveTo(p1.x, p1.y);
					context.lineTo(x1.x, x1.y);
				}
				else {
					context.moveTo(x1.x, x1.y);
					context.lineTo(p1.x, p1.y);
					context.lineTo(x2.x, x2.y);
					context.lineTo(p2.x, p2.y);
				}
			break;
		}
		context.stroke();
	}

	drawShape(shape, context) {
		context.strokeStyle = '#0000ff';
		context.beginPath();
		switch (shape.m_type) {
			case b2.Shape.e_circleShape:
			{
				var circle = shape;
				var pos = circle.m_position;
				var r = circle.m_radius;
				var segments = 16.0;
				var theta = 0.0;
				var dtheta = 2.0 * Math.PI / segments;
				// draw circle
				context.moveTo(pos.x + r, pos.y);
				for (var i = 0; i < segments; i++) {
					var d = new b2.Vec2(r * Math.cos(theta), r * Math.sin(theta));
					var v = b2.Math.AddVV(pos, d);
					context.lineTo(v.x, v.y);
					theta += dtheta;
				}
				context.lineTo(pos.x + r, pos.y);

				// draw radius
				context.moveTo(pos.x, pos.y);
				var ax = circle.m_R.col1;
				var pos2 = new b2.Vec2(pos.x + r * ax.x, pos.y + r * ax.y);
				context.lineTo(pos2.x, pos2.y);

				// draw gameObject
				let userData = shape.GetUserData();
				if (userData != null && userData.setPosition instanceof Function)
				userData.setPosition(pos.x, pos.y);
			}
			break;
			case b2.Shape.e_polyShape:
			{
				var poly = shape;
				var tV = b2.Math.AddVV(poly.m_position, b2.Math.b2MulMV(poly.m_R, poly.m_vertices[0]));
				context.moveTo(tV.x, tV.y);
				for (var i = 0; i < poly.m_vertexCount; i++) {
					var v = b2.Math.AddVV(poly.m_position, b2.Math.b2MulMV(poly.m_R, poly.m_vertices[i]));
					context.lineTo(v.x, v.y);
				}
				context.lineTo(tV.x, tV.y);

				// draw gameObject
				let userData = shape.GetUserData();
				if (userData != null && userData.setPosition instanceof Function)
				userData.setPosition(pos.x, pos.y);
			}
			break;
		}
		context.stroke();
	}
}

